/* 
 * Copyright (c) 2004-2005 Massachusetts Institute of Technology. This code was
 * developed as part of the Haystack (http://haystack.lcs.mit.edu/) research 
 * project at MIT. Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation files (the 
 * "Software"), to deal in the Software without restriction, including without 
 * limitation the rights to use, copy, modify, merge, publish, distribute, 
 * sublicense, and/or sell copies of the Software, and to permit persons to whom
 * the Software is furnished to do so, subject to the following conditions: 
 * 
 * The above copyright notice and this permission notice shall be included in 
 * all copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER  
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE. 
 */
/*
 * Created on Oct 12, 2004
 *
 */
package jiggle.relo;

import jiggle.AbstractForceLaw;
import jiggle.Cell;
import jiggle.Graph;
import jiggle.Vertex;

/**
 * This ForceLaw essentially models a attraction force towards the origin
 * It prevents nodes from drifting away and keep the compactness of the
 * graph
 * 
 * @author vineet
 *  
 */

public class OriginAttractionLaw extends AbstractForceLaw {

    AbstractForceLaw attrLaw;
    
    Cell origin;

    public OriginAttractionLaw(Graph g, double k, AbstractForceLaw attrLaw, AbstractForceLaw repulseLaw) {
        super(g, k);
        this.attrLaw = attrLaw;
        origin = new Vertex(g);
        double[] originNfo;
        originNfo = origin.getCoords();
        for (int i = 0; i < originNfo.length; i++) {
            originNfo[i] = 0;
        }
        originNfo = origin.getSize();
        for (int i = 0; i < originNfo.length; i++) {
            originNfo[i] = 0;
        }
    }
    
    public void setOrigin(int x, int y) {
        double[] originNfo;
        originNfo = origin.getCoords();
        originNfo[0] = x;
        originNfo[1] = y;
    }

    @Override
    public double pairwiseWeights (double pref, double curr) {
        return attrLaw.pairwiseWeights(pref, curr) / 4;
	}

    @Override
    public void apply(double[][] negativeGradient) {
        double oldPrefEdgeLength = attrLaw.preferredEdgeLength;
        int n = graph.getNumberOfVertices();
        for (int i = 0; i < n; i++) {
            Cell v = graph.vertices.get(i);
            if (!(v instanceof Vertex)) continue;
            
            applyForCells(negativeGradient, v, origin);
        }
        attrLaw.preferredEdgeLength = oldPrefEdgeLength;
    }
}
